/*
 * @Author: xiaosihan
 * @Date: 2024-08-17 20:12:52
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2025-01-28 04:05:18
 */

import utils from "@utils";
import { throttle } from "lodash";
import {
  AmbientLight,
  DirectionalLight,
  DirectionalLightHelper,
  Intersection,
  PointLight,
  Vector2,
  Vector3,
} from "three";
import ThreeBase from "three-base";
import { degToRad } from "three/src/math/MathUtils";
import Terrain from "./component3d/Terrain/Terrain";
import terrain1JSON from "./component3d/Terrain/terrain1.json";
import People from "./component3d/people/People";
import Road from "./component3d/Road/Road";
import SphereMesh from "@views/home/component3d/SphereMesh/SphereMesh";

/**
 * @class Home2Render
 * @extends {ThreeBase}
 */
class Home2Render extends ThreeBase {
  constructor() {
    super();
  }

  // 环境光
  ambientLight = (() => {
    const ambientLight = new AmbientLight("#fff", 1);
    this.scene.add(ambientLight);
    return ambientLight;
  })();

  //点光源
  pointLight = (() => {
    const pointLight = new PointLight("#fff", 1);
    pointLight.position.set(50, 40, 50);
    this.scene.add(pointLight);
    return pointLight;
  })();

  // 方向光
  directionalLight = (() => {
    const directionalLight = new DirectionalLight("#fff", 2);
    directionalLight.position.set(-10, 10, 10);
    directionalLight.target.position.set(0, 0, 0);
    directionalLight.castShadow = true;
    directionalLight.shadow.camera.far = 1000;
    directionalLight.shadow.bias = -0.0001;
    directionalLight.shadow.mapSize.set(1024, 1024);
    this.scene.add(directionalLight);
    return directionalLight;
  })();

  //方向光
  directionalLightHelper = (() => {
    const directionalLightHelper = new DirectionalLightHelper(
      this.directionalLight
    );
    if (utils.isDev) {
      this.scene.add(directionalLightHelper);
    }
    return directionalLightHelper;
  })();

  init() {
    super.init();
    this.axesHelper.visible = utils.isDev;
    this.gridHelper.visible = utils.isDev;
    this.renderer.shadowMap.enabled = true;
    this.controls.screenSpacePanning = false;
    // this.controls.enableZoom = false;
    // this.controls.enablePan = false;

    // this.resetLookAt({
    //     center: new Vector3(0, 0, 0),
    //     position: new Vector3(200, 200, 200)
    // });

    this.setCamera({
      target: new Vector3(0, 0, 0),
      pzimuthalAngle: 45,
      polarAngle: 45,
      distance: 200,
    });

    this.renderer.domElement.addEventListener("mousedown", (e: any) => {
      const { width, height } = this.renderer.domElement;
      const mosePosition = new Vector2(
        (e.offsetX / width) * devicePixelRatio * 2 - 1,
        -((e.offsetY / height) * devicePixelRatio) * 2 + 1
      );

      const intersection: Intersection =
        (e.ctrlKey || e.shiftKey) &&
        this.terrain.intersect(mosePosition, this.getCamera());
      if (intersection) {
        if (e.ctrlKey) {
          // 按住 ctrl 是编辑地形
          this.terrain.mousedown(intersection);
        } else if (e.shiftKey) {
          // 按住 shaift 是种树
          console.log("种树的位置", intersection.point);
        }
        this.controls.enabled = false;
      } else {
        this.controls.enabled = true;
      }
    });

    // 鼠标滑动节流
    const mousemove = throttle((e: any) => {
      const { width, height } = this.renderer.domElement;
      const mosePosition = new Vector2(
        (e.offsetX / width) * devicePixelRatio * 2 - 1,
        -((e.offsetY / height) * devicePixelRatio) * 2 + 1
      );
      const intersection: Intersection =
        e.ctrlKey && this.terrain.intersect(mosePosition, this.getCamera());
      if (intersection) {
        this.terrain.mousemove(intersection);
      }
    }, 30);

    this.renderer.domElement.addEventListener("mousemove", (e: any) => {
      mousemove(e);
    });

    this.renderer.domElement.addEventListener("mouseup", (e: any) => {
      this.terrain.mouseup();
      this.controls.enabled = true;
    });
  }

  //地形
  terrain = (() => {
    const terrain = new Terrain();
    terrain.importData(terrain1JSON);
    this.add(terrain);
    return terrain;
  })();

  //人1
  people1 = (() => {
    const people = new People("./model/Soldier.glb");

    // 设置路径
    people.setPath([
      new Vector3(-30, 0, -30),
      new Vector3(30, 0, -30),
      new Vector3(30, 0, 30),
      new Vector3(-30, 0, 30),
    ]);

    //时时获取地形高度
    people.addEventListener("move", () => {
      const { x, z } = people.position;
      const y = this.terrain.getYByXZ(x, z);
      people.position.setY(y);
    });
    this.scene.add(people);
    return people;
  })();

  //人2
  people2 = (() => {
    const people = new People("./model/Soldier.glb");

    // 设置路径
    people.setPath([
      new Vector3(-20, 0, -20),
      new Vector3(20, 0, -20),
      new Vector3(20, 0, 20),
      new Vector3(-20, 0, 20),
    ]);

    //时时获取地形高度
    people.addEventListener("move", () => {
      const { x, z } = people.position;
      const y = this.terrain.getYByXZ(x, z);
      people.position.setY(y);
    });
    this.scene.add(people);
    return people;
  })();

  //公路
  road = (() => {
    const road = new Road({
      closed: true, // 是否闭合路径
      shapePath: [
        [-2, 0],
        [2, 0],
      ], // 平面路径
      paths: [
        // 挤出路径的点位置    转弯半径   转弯分段数     当前点的缩放            取个名字
        {
          vector3: [-60, 0, -60],
          radius: 4,
          segments: 20,
          scale: { x: 1, y: 1 },
          name: "路口1",
        },
        {
          vector3: [60, 0, -60],
          radius: 4,
          segments: 20,
          scale: { x: 1, y: 1 },
          name: "路口2",
        },
        {
          vector3: [60, 0, 60],
          radius: 4,
          segments: 20,
          scale: { x: 1, y: 1 },
          name: "路口3",
        },
        {
          vector3: [-60, 0, 60],
          radius: 4,
          segments: 20,
          scale: { x: 1, y: 1 },
          name: "路口4",
        },
      ], // 路径的
    });
    this.add(road);
    return road;
  })();

  //特效着色器1
  sphereMesh = (() => {
    const sphereMesh = new SphereMesh();
    sphereMesh.scale.set(200, 200, 200);
    this.add(sphereMesh);
    return sphereMesh;
  })();

  cameraPosition = new Vector3();
  cameraCenter = new Vector3();

  setCamera({
    target,
    pzimuthalAngle,
    polarAngle,
    distance,
  }: {
    target: Vector3;
    pzimuthalAngle: number;
    polarAngle: number;
    distance: number;
  }) {
    this.controls.target.copy(target);
    const y = Math.sin(degToRad(polarAngle));
    const x =
      Math.cos(degToRad(pzimuthalAngle)) * Math.cos(degToRad(polarAngle));
    const z =
      Math.sin(degToRad(pzimuthalAngle)) * Math.cos(degToRad(polarAngle));
    const cameraPosition = new Vector3(x, y, z).setLength(distance).add(target);
    this.getCamera().position.copy(cameraPosition);
    this.controls.update();
  }

  render(): void {
    super.render();
    this.cameraPosition.copy(this.getCamera().position);
    this.cameraCenter.copy(this.controls.target);
    let d = this.cameraPosition.distanceTo(this.cameraCenter);
    d = Math.max(d, 10);

    // 动态修改阴影范围
    this.directionalLight.target.position.copy(this.cameraCenter);
    this.directionalLight.shadow.camera.left = -d;
    this.directionalLight.shadow.camera.bottom = -d;
    this.directionalLight.shadow.camera.top = d;
    this.directionalLight.shadow.camera.right = d;
    this.directionalLight.position
      .copy(this.cameraCenter)
      .add(new Vector3(-d, d / 2, -d));
    this.directionalLight.shadow.camera.updateProjectionMatrix();
    this.directionalLightHelper.update();
  }
}

const home2Renderer = (window.home2Renderer = new Home2Render());

export default home2Renderer;
